#include "stdafx.h"
#include "WsgiInputStream.h"

PYTHON_ACCESSABLE PyObject* InputStream_read(InputStreamObject* self, PyObject* args) {
	int lengthToRead = 0;

	if(!PyArg_ParseTuple(args, "|i:read", &lengthToRead)) {
		return NULL;
	}
	if(0 >= lengthToRead) {
		lengthToRead = 1;
	}

	//TODO: SHOULD check Content-Length header, if available, and never read past that.
	//Of course, the IIS input buffer is only so big anyway, so I'm not sure this
	// matters too much.
	std::string requestData = self->Request->Read(lengthToRead);

	PyObject* pythonString = PyString_FromStringAndSize(requestData.c_str(), requestData.length());
	return pythonString;
}

PYTHON_ACCESSABLE PyObject* InputStream_readline(InputStreamObject* self, PyObject* args) {
	long size = 0;

	//PEP 333 says there is a size argument, but we shouldn't
	// try to use it...because its annoying.
	if(!PyArg_ParseTuple(args, "|l:readline", &size)) {
		return NULL;
	}

	std::string requestData = self->Request->ReadLine();

	PyObject* pythonString = PyString_FromStringAndSize(requestData.c_str(), requestData.length());
	return pythonString;
}

PYTHON_ACCESSABLE PyObject* InputStream_readlines(InputStreamObject* self, PyObject* args) {
	long linesToRead = 0L;

	//According to the PEP 333 spec, I'm supposed to accept a "hint" argument
	// but I'm as free to ignore it as is the caller...so I will.
	if(!PyArg_ParseTuple(args, "|l:readlines", &linesToRead)) {
		return NULL;
	}

	PyObject* outputList = PyList_New(0);
	for(long linesRead = 0; linesRead < linesToRead; linesRead++) {
		std::string line = self->Request->ReadLine();
		PyObject* pythonString = PyString_FromStringAndSize(line.c_str(), line.length());
		
		if(-1 == PyList_Append(outputList, pythonString)) {
			Py_DECREF(outputList);
			return NULL;
		}
	}

	return outputList;
}

PYTHON_ACCESSABLE PyObject* InputStream_iter(InputStreamObject* self) {
	Py_INCREF(self);
	return (PyObject*)self;

}
PYTHON_ACCESSABLE PyObject* InputStream_iternext(InputStreamObject* self) {
	std::string line = self->Request->ReadLine();

	if(line.length() <= 0) {
		PyErr_SetObject(PyExc_StopIteration, Py_None);
		return NULL;
	}

	PyObject* outputString = PyString_FromStringAndSize(line.c_str(), line.length());
	return outputString;
}

static void InputStream_dealloc(InputStreamObject* inputStream) {
	GILock lock;
	PyObject_Del((PyObject*)inputStream);
}

PYTHON_ACCESSABLE PyMethodDef InputStreamMethods[] = {
	{ "read", (PyCFunction)InputStream_read, METH_VARARGS, NULL },
	{ "readline", (PyCFunction)InputStream_readline, METH_VARARGS, NULL },
	{ "readlines", (PyCFunction)InputStream_readlines, METH_VARARGS, NULL },
	{ NULL }
};

PyTypeObject InputStreamType = {
	PyVarObject_HEAD_INIT(NULL, 0)
	"isapi_python.InputStream",		//tp_name
	sizeof(InputStreamObject),		//tp_basicsize
	0,								//tp_itemsize
	// methods
	(destructor)InputStream_dealloc, //tp_dealloc
	NULL,							//tp_print
	NULL,							//tp_getattr
	NULL,							//tp_setattr
	NULL,							//tp_compare
	NULL,							//tp_repr
	NULL,							//tp_as_number
	NULL,							//tp_as_sequence
	NULL,							//tp_as_mapping
	NULL,							//tp_hash
	NULL,							//tp_call
	NULL,							//tp_str
	NULL,							//tp_getattro
	NULL,							//tp_setattro
	NULL,							//tp_as_buffer
	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, //tp_flags
	NULL,							//tp_doc
	NULL,							//tp_traverse
	NULL,							//tp_clear
	NULL,							//tp_richcompare
	NULL,							//tp_weaklistoffset
	(getiterfunc)InputStream_iter,	    //tp_iter,
	(iternextfunc)InputStream_iternext,	//tp_iternext
	InputStreamMethods				    //tp_methods
};